#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

#include <netinet/in.h>    // for sockaddr_in
#include <sys/types.h>    // for socket
#include <sys/socket.h>    // for socket
#include <arpa/inet.h>    //for inet_ntoa 
#include <sys/un.h>     // for unix domain socket
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>   //select time
#include <unistd.h>

#include "iec10x.h"
#include "CPxTime2a.h"
#include "unixsock.h"


int unixsock = 0;

struct iec10x demobus = {0};




static void iec104_puts(uint8_t * info , int len)
{
	if (unixsock) {
		write(unixsock , info , len);
	}
}



void * iec104_poll(void *arg)
{
	size_t time = 0;
	struct timeval timer100ms ;
	while( 1 ) {
		timer100ms.tv_sec = 0;
		timer100ms.tv_usec = 50000 ;
		select(0, NULL, NULL, NULL, &timer100ms);
		time += 50 ;
		// 处理协议栈 100ms 超时/定时任务，此处不需要太精确
		iec10x_periodic_handle(time); 
	}
}

void * iec104_recv(void *arg)
{
	unsigned char databuf[1024];
	int readn;
	while( 1 ) {
		readn = read(unixsock,databuf,sizeof(databuf));
		if (readn < 1) {
			printf("recv error.exit.\r\n");
			exit(1);
		}
		iec10x_recv(&demobus,databuf,readn);
	}
}



void * server_listen(void * arg)
{
	pthread_t newthread ;
	struct sockaddr_un client_un = {0};  
	socklen_t slen = sizeof(struct sockaddr_un);
	int servlisten = unix_socket_server("m104f",8);
	int newconn;
	while(1) {
		newconn = accept(servlisten,(struct sockaddr*)&client_un,&slen);
		if (newconn < 0) {
			continue ;
		}
		else
		if (unixsock) {
			printf("connect existing..\r\n");
			close(unixsock);
		}
		else {
			printf("connect successful.\r\n");
			unixsock = newconn ;
			pthread_create(&newthread,NULL,iec104_recv  ,NULL);
		}
	}
	return NULL;
}


void dir_info(void * bus , struct iec_slist * listhead ,int result)
{
	struct iec_slist * node = listhead;
	struct file_node * fnode ;

	if (result != 0) {
		printf("error.\r\n");
		return ;
	}

	while (node != NULL) {
		fnode = container_of(node, struct file_node,node);
		node  = node->next;
		printf("%-20s(%02d/%02d/%02d %02d:%02d) size:%d\r\n",
			fnode->name,
			fnode->ftime.year,fnode->ftime.month,fnode->ftime.day.date,
			fnode->ftime.hour,fnode->ftime.min,
			fnode->fsize);
	}
}


void fs_callback(void * bus, const char * filename ,int result)
{
	printf("%d,%s\r\n",result,filename);
}


int main(int argc, char *argv[])
{
	pthread_t newthread;
	struct iec104cfg cfg = {0};

	if (argc < 2) {
		printf("Usage:cmd [name]\r\n");
		return -1;
	}
	else {
		printf("target file:%s\r\n", argv[1]);
	}

	iec10x_protocol_init();
	
	cfg.haltx    = iec104_puts ;
	cfg.print    = printf      ;
	cfg.dbglevel = 2           ;
	cfg.mode     = 1           ;
	iec10x_bus_init(&demobus,104,&cfg,NULL);

	pthread_create(&newthread,NULL,server_listen,NULL);
	pthread_create(&newthread,NULL,iec104_poll  ,NULL);
	
	printf("standby...\r\n");

	getchar();
	
	#if 0
		/* 召唤从站的 iecfile 目录文件 */
		iec10xmst_readdir(&demobus,"iecfile",0,NULL,NULL,dir_info);
		getchar();
	#endif

	#if 0
		/* 召唤从站的 argv[1] 文件，并存放于本地 iecrecv 文件夹 */
		iec10xmst_fget(&demobus,"iecrecv",argv[1],fs_callback);
		getchar();
	#endif

	#if 1
		/* 发送本地文件夹 iecfile 的文件 argv[1] 至从站 */
		iec10xmst_fput(&demobus,"iecfile",argv[1],fs_callback);
		getchar();
	#endif

	return 0;
}
